{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "dd228051",
   "metadata": {},
   "outputs": [],
   "source": [
    "from pathlib import Path\n",
    "import glob as gb\n",
    "import re\n",
    "import os"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "b396635d",
   "metadata": {},
   "outputs": [],
   "source": [
    "ROOT_DIR = Path(\".\").absolute().parent.parent\n",
    "MODEL_DIR = ROOT_DIR / \"src\" / \"model\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "493bfb43",
   "metadata": {},
   "outputs": [],
   "source": [
    "cpp_files = sorted(list(MODEL_DIR.glob(\"*.cpp\")))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "a97065e3",
   "metadata": {},
   "outputs": [],
   "source": [
    "class ComponentTypeInfo:\n",
    "    def __init__(self, is_simple: bool, simple_return: str = None, func_body: str = None):\n",
    "        self.is_simple = is_simple\n",
    "        self.simple_return = simple_return\n",
    "        self.func_body = func_body\n",
    "\n",
    "    def __repr__(self):\n",
    "        if self.is_simple:\n",
    "            return self.simple_return\n",
    "        else:\n",
    "            return \"Complex\"\n",
    "\n",
    "    def __str__(self):\n",
    "        if self.is_simple:\n",
    "            return self.simple_return\n",
    "        else:\n",
    "            return f\"Complex: {func_body}\"\n",
    "\n",
    "\n",
    "class ClassInfo:\n",
    "    def __init__(self, class_name: str):\n",
    "        self.class_name = class_name\n",
    "        self.component_type = None\n",
    "        self.cooling_fuel_types = None\n",
    "        self.heating_fuel_types = None\n",
    "        self.appg_heating_fuel_types = None\n",
    "\n",
    "    @staticmethod\n",
    "    def header():\n",
    "        return [\"Class_Name\", \"ComponentType\", \"coolingFuelTypes\", \"heatingFuelTypes\", \"appGHeatingFuelTypes\"]\n",
    "\n",
    "    def __repr__(self):\n",
    "        return f\"{self.class_name},{self.component_type.__repr__()},{self.cooling_fuel_types.__repr__()},{self.heating_fuel_types.__repr__()},{self.appg_heating_fuel_types.__repr__()}\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "cb16f193",
   "metadata": {},
   "outputs": [],
   "source": [
    "RE_SIMPLE_COMPTYPE = re.compile(r\"return ComponentType::(Cooling|Heating|None);\")\n",
    "RE_SIMPLE_FUELTYPE = re.compile(r\"return (.*);\")\n",
    "\n",
    "RE_INSERT_FUELTYPE = re.compile(r\"result.insert\\(FuelType::(.*?)\\);\")\n",
    "RE_INSERT_CONVERTFUELTYPE = re.compile(r\"result.insert\\(FuelType\\(.*?\\)\\);\")\n",
    "\n",
    "RE_INSERT_FUELTYPE_APPG = re.compile(r\"result.insert\\(AppGFuelType::(.*?)\\);\")\n",
    "RE_INSERT_CONVERTFUELTYPE_APPG = re.compile(r\"result.insert\\(convertFuelTypeToAppG\\(.*?\\)\\);\")\n",
    "\n",
    "\n",
    "RE_GET_AIRLOOP_HEATING = re.compile(\n",
    "    r\"\\s*if \\(auto a_ = airLoopHVAC\\(\\)\\) {\\s*return a_->heatingFuelTypes\\(\\);\\s*}\\s*return {};\\s*\", re.DOTALL\n",
    ")\n",
    "RE_GET_AIRLOOP_COOLING = re.compile(\n",
    "    r\"\\s*if \\(auto a_ = airLoopHVAC\\(\\)\\) {\\s*return a_->coolingFuelTypes\\(\\);\\s*}\\s*return {};\\s*\", re.DOTALL\n",
    ")\n",
    "RE_GET_AIRLOOP_APPG = re.compile(\n",
    "    r\"\\s*if \\(auto a_ = airLoopHVAC\\(\\)\\) {\\s*return a_->appGHeatingFuelTypes\\(\\);\\s*}\\s*return {};\\s*\", re.DOTALL\n",
    ")\n",
    "\n",
    "\n",
    "RE_GET_PLANTLOOP_HEATING = re.compile(\n",
    "    r\"\\s*if \\(auto p_ = plantLoop\\(\\)\\) {\\s*return p_->heatingFuelTypes\\(\\);\\s*}\\s*return {};\\s*\", re.DOTALL\n",
    ")\n",
    "RE_GET_PLANTLOOP_COOLING = re.compile(\n",
    "    r\"\\s*if \\(auto p_ = plantLoop\\(\\)\\) {\\s*return p_->coolingFuelTypes\\(\\);\\s*}\\s*return {};\\s*\", re.DOTALL\n",
    ")\n",
    "RE_GET_PLANTLOOP_APPG = re.compile(\n",
    "    r\"\\s*if \\(auto p_ = plantLoop\\(\\)\\) {\\s*return p_->appGHeatingFuelTypes\\(\\);\\s*}\\s*return {};\\s*\", re.DOTALL\n",
    ")\n",
    "\n",
    "RE_INSERT_AIRLOOP_HEATING = re.compile(\n",
    "    r\"\\s*if \\(auto a_ = airLoopHVAC\\(\\)\\) {\\s*for \\(auto ft : a_->heatingFuelTypes\\(\\)\\) {\\s*result.insert\\(ft\\);\\s*}\\s*}\",\n",
    "    re.DOTALL,\n",
    ")\n",
    "\n",
    "RE_INSERT_AIRLOOP_COOLING = re.compile(\n",
    "    r\"\\s*if \\(auto a_ = airLoopHVAC\\(\\)\\) {\\s*for \\(auto ft : a_->coolingFuelTypes\\(\\)\\) {\\s*result.insert\\(ft\\);\\s*}\\s*}\",\n",
    "    re.DOTALL,\n",
    ")\n",
    "\n",
    "RE_INSERT_AIRLOOP_APPG = re.compile(\n",
    "    r\"\\s*if \\(auto a_ = airLoopHVAC\\(\\)\\) {\\s*for \\(auto ft : a_->appGHeatingFuelTypes\\(\\)\\) {\\s*result.insert\\(ft\\);\\s*}\\s*}\",\n",
    "    re.DOTALL,\n",
    ")\n",
    "\n",
    "\n",
    "RE_INSERT_PLANTLOOP_HEATING = re.compile(\n",
    "    r\"\\s*if \\(auto p_ = plantLoop\\(\\)\\) {\\s*for \\(auto ft : p_->heatingFuelTypes\\(\\)\\) {\\s*result.insert\\(ft\\);\\s*}\\s*}\",\n",
    "    re.DOTALL,\n",
    ")\n",
    "\n",
    "RE_INSERT_PLANTLOOP_COOLING = re.compile(\n",
    "    r\"\\s*if \\(auto p_ = plantLoop\\(\\)\\) {\\s*for \\(auto ft : p_->coolingFuelTypes\\(\\)\\) {\\s*result.insert\\(ft\\);\\s*}\\s*}\",\n",
    "    re.DOTALL,\n",
    ")\n",
    "\n",
    "RE_INSERT_PLANTLOOP_APPG = re.compile(\n",
    "    r\"\\s*if \\(auto p_ = plantLoop\\(\\)\\) {\\s*for \\(auto ft : p_->appGHeatingFuelTypes\\(\\)\\) {\\s*result.insert\\(ft\\);\\s*}\\s*}\",\n",
    "    re.DOTALL,\n",
    ")\n",
    "\n",
    "RE_INSERT_REHEAT_COIL = re.compile(\n",
    "    r\"\\s*for \\(auto ft : reheatCoil\\(\\).heatingFuelTypes\\(\\)\\) {\\s*result.insert\\(ft\\);\\s*}\", re.DOTALL\n",
    ")\n",
    "\n",
    "RE_INSERT_REHEAT_COIL_APPG = re.compile(\n",
    "    r\"\\s*for \\(auto ft : reheatCoil\\(\\).appGHeatingFuelTypes\\(\\)\\) {\\s*result.insert\\(ft\\);\\s*}\", re.DOTALL\n",
    ")\n",
    "\n",
    "\n",
    "RE_INSERT_HEAT_COIL = re.compile(\n",
    "    r\"\\s*for \\(auto ft : heatingCoil\\(\\).heatingFuelTypes\\(\\)\\) {\\s*result.insert\\(ft\\);\\s*}\", re.DOTALL\n",
    ")\n",
    "\n",
    "RE_INSERT_OPT_HEAT_COIL = re.compile(\n",
    "    r\"\\s*for \\(auto ft : hc_->heatingFuelTypes\\(\\)\\) {\\s*result.insert\\(ft\\);\\s*}\", re.DOTALL\n",
    ")\n",
    "\n",
    "RE_INSERT_HEAT_COIL_APPG = re.compile(\n",
    "    r\"\\s*for \\(auto ft : heatingCoil\\(\\).appGHeatingFuelTypes\\(\\)\\) {\\s*result.insert\\(ft\\);\\s*}\", re.DOTALL\n",
    ")\n",
    "\n",
    "RE_INSERT_OPT_HEAT_COIL_APPG = re.compile(\n",
    "    r\"\\s*for \\(auto ft : hc_->appGHeatingFuelTypes\\(\\)\\) {\\s*result.insert\\(ft\\);\\s*}\", re.DOTALL\n",
    ")\n",
    "\n",
    "\n",
    "RE_INSERT_SUPHC_COIL = re.compile(\n",
    "    r\"\\s*for \\(auto ft : supplementalHeatingCoil\\(\\).heatingFuelTypes\\(\\)\\) {\\s*result.insert\\(ft\\);\\s*}\", re.DOTALL\n",
    ")\n",
    "\n",
    "RE_INSERT_OPT_SUPHC_COIL = re.compile(\n",
    "    r\"\\s*for \\(auto ft : supHC_->heatingFuelTypes\\(\\)\\) {\\s*result.insert\\(ft\\);\\s*}\", re.DOTALL\n",
    ")\n",
    "\n",
    "RE_INSERT_SUPHC_COIL_APPG = re.compile(\n",
    "    r\"\\s*for \\(auto ft : supplementalHeatingCoil\\(\\).appGHeatingFuelTypes\\(\\)\\) {\\s*result.insert\\(ft\\);\\s*}\", re.DOTALL\n",
    ")\n",
    "\n",
    "RE_INSERT_OPT_SUPHC_COIL_APPG = re.compile(\n",
    "    r\"\\s*for \\(auto ft : supHC_->appGHeatingFuelTypes\\(\\)\\) {\\s*result.insert\\(ft\\);\\s*}\", re.DOTALL\n",
    ")\n",
    "\n",
    "\n",
    "RE_INSERT_COOL_COIL = re.compile(\n",
    "    r\"\\s*for \\(auto ft : coolingCoil\\(\\).coolingFuelTypes\\(\\)\\) {\\s*result.insert\\(ft\\);\\s*}\", re.DOTALL\n",
    ")\n",
    "\n",
    "\n",
    "RE_INSERT_OPT_COOL_COIL = re.compile(\n",
    "    r\"\\s*for \\(auto ft : cc_->coolingFuelTypes\\(\\)\\) {\\s*result.insert\\(ft\\);\\s*}\", re.DOTALL\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "7443cca1",
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_func_body(lines, i):\n",
    "    c = lines[i].count(\"{\") - lines[i].count(\"}\")\n",
    "    k = i\n",
    "    while c != 0:\n",
    "        k += 1\n",
    "        c += lines[k].count(\"{\") - lines[k].count(\"}\")\n",
    "    func_body = \"\\n\".join(lines[i : k + 1])\n",
    "    func_body = func_body[func_body.find(\"{\") + 1 : func_body.rfind(\"}\")].strip()\n",
    "    return k, func_body"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "f32698fe",
   "metadata": {},
   "outputs": [],
   "source": [
    "def parse_coolingFuelTypeFuncBod(func_body: str):\n",
    "    if m := RE_SIMPLE_FUELTYPE.match(func_body):\n",
    "        fuel_type = m.groups()[0].strip()\n",
    "        if fuel_type == \"{}\":\n",
    "            fuel_type = \"\"\n",
    "        elif fuel_type.startswith(\"{\") and fuel_type.endswith(\"}\"):\n",
    "            fuel_type = fuel_type.replace(\"FuelType::\", \"\")\n",
    "            if \",\" in fuel_type:\n",
    "                fuel_type = f'\"{fuel_type}\"'\n",
    "            else:\n",
    "                fuel_type = fuel_type[1:-1]\n",
    "        return ComponentTypeInfo(is_simple=True, simple_return=fuel_type, func_body=func_body)\n",
    "\n",
    "    if RE_GET_AIRLOOP_COOLING.match(func_body):\n",
    "        return ComponentTypeInfo(is_simple=True, simple_return=\"airLoopHVAC_->coolingFuelTypes()\", func_body=func_body)\n",
    "\n",
    "    if RE_GET_PLANTLOOP_COOLING.match(func_body):\n",
    "        return ComponentTypeInfo(is_simple=True, simple_return=\"plantLoop_->coolingFuelTypes()\", func_body=func_body)\n",
    "\n",
    "    s = []\n",
    "    if m := RE_INSERT_FUELTYPE.search(func_body):\n",
    "        s.append(m.groups()[0])\n",
    "    if RE_INSERT_CONVERTFUELTYPE.search(func_body):\n",
    "        s.append(\"fuelType()\")\n",
    "    if RE_INSERT_AIRLOOP_COOLING.search(func_body):\n",
    "        s.append(\"airLoopHVAC_->coolingFuelTypes()\")\n",
    "    if RE_INSERT_PLANTLOOP_COOLING.search(func_body):\n",
    "        s.append(\"plantLoop_->coolingFuelTypes()\")\n",
    "    if RE_INSERT_COOL_COIL.search(func_body):\n",
    "        s.append(\"cc.coolingFuelTypes()\")\n",
    "    if RE_INSERT_OPT_COOL_COIL.search(func_body):\n",
    "        s.append(\"cc_->coolingFuelTypes()\")\n",
    "\n",
    "    if s:\n",
    "        # print(s)\n",
    "        return ComponentTypeInfo(is_simple=True, simple_return=\" + \".join(s), func_body=func_body)\n",
    "\n",
    "    return ComponentTypeInfo(is_simple=False, func_body=func_body)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "734196a5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"{Electricity, OtherFuel_1}\""
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "func_body = \"\"\"\n",
    "{\n",
    "      std::set<FuelType> result;\n",
    "      result.insert(FuelType::Electricity);\n",
    "      if (auto p_ = plantLoop()) {\n",
    "        for (auto ft : p_->coolingFuelTypes()) {\n",
    "          result.insert(ft);\n",
    "        }\n",
    "      }\n",
    "      return {};\n",
    "    }\n",
    "\"\"\"\n",
    "func_body = \"return {FuelType::Electricity, FuelType::OtherFuel_1};  // TODO: is that right?\"\n",
    "parse_coolingFuelTypeFuncBod(func_body)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "cdce9e6c",
   "metadata": {},
   "outputs": [],
   "source": [
    "def parse_heatingFuelTypeFuncBod(func_body: str):\n",
    "    if m := RE_SIMPLE_FUELTYPE.match(func_body):\n",
    "        fuel_type = m.groups()[0].strip()\n",
    "        if fuel_type == \"{}\":\n",
    "            fuel_type = \"\"\n",
    "        elif fuel_type.startswith(\"{\") and fuel_type.endswith(\"}\"):\n",
    "            fuel_type = fuel_type.replace(\"FuelType::\", \"\")\n",
    "            if \",\" in fuel_type:\n",
    "                fuel_type = f'\"{fuel_type}\"'\n",
    "            else:\n",
    "                fuel_type = fuel_type[1:-1]\n",
    "        return ComponentTypeInfo(is_simple=True, simple_return=fuel_type)\n",
    "\n",
    "    if RE_GET_AIRLOOP_HEATING.match(func_body):\n",
    "        return ComponentTypeInfo(is_simple=True, simple_return=\"airLoopHVAC_->heatingFuelTypes()\")\n",
    "\n",
    "    if RE_GET_PLANTLOOP_HEATING.match(func_body):\n",
    "        return ComponentTypeInfo(is_simple=True, simple_return=\"plantLoop_->heatingFuelTypes()\")\n",
    "\n",
    "    s = []\n",
    "    if m := RE_INSERT_FUELTYPE.search(func_body):\n",
    "        s.append(m.groups()[0])\n",
    "    if RE_INSERT_CONVERTFUELTYPE.search(func_body):\n",
    "        s.append(\"fuelType()\")\n",
    "\n",
    "    if RE_INSERT_AIRLOOP_HEATING.search(func_body):\n",
    "        s.append(\"airLoopHVAC_->heatingFuelTypes()\")\n",
    "    if RE_INSERT_PLANTLOOP_HEATING.search(func_body):\n",
    "        s.append(\"airLoopHVAC_->heatingFuelTypes()\")\n",
    "    if RE_INSERT_HEAT_COIL.search(func_body):\n",
    "        s.append(\"hc.heatingFuelTypes()\")\n",
    "    if RE_INSERT_OPT_HEAT_COIL.search(func_body):\n",
    "        s.append(\"hc_->heatingFuelTypes()\")\n",
    "    if RE_INSERT_REHEAT_COIL.search(func_body):\n",
    "        s.append(\"reheatCoil.heatingFuelTypes()\")\n",
    "    if RE_INSERT_SUPHC_COIL.search(func_body):\n",
    "        s.append(\"supHC.heatingFuelTypes()\")\n",
    "    if RE_INSERT_OPT_SUPHC_COIL.search(func_body):\n",
    "        s.append(\"supHC_->heatingFuelTypes()\")\n",
    "    if s:\n",
    "        # print(s)\n",
    "        return ComponentTypeInfo(is_simple=True, simple_return=\" + \".join(s))\n",
    "\n",
    "    return ComponentTypeInfo(is_simple=False, func_body=func_body)\n",
    "\n",
    "\n",
    "def parse_appGHeatingFuelTypeFuncBod(func_body: str):\n",
    "    if m := RE_SIMPLE_FUELTYPE.match(func_body):\n",
    "        fuel_type = m.groups()[0].strip()\n",
    "        if fuel_type == \"{}\":\n",
    "            fuel_type = \"\"\n",
    "        elif fuel_type.startswith(\"{\") and fuel_type.endswith(\"}\"):\n",
    "            fuel_type = fuel_type.replace(\"AppGFuelType::\", \"\")\n",
    "            if \",\" in fuel_type:\n",
    "                fuel_type = f'\"{fuel_type}\"'\n",
    "            else:\n",
    "                fuel_type = fuel_type[1:-1]\n",
    "        return ComponentTypeInfo(is_simple=True, simple_return=fuel_type, func_body=func_body)\n",
    "\n",
    "    if RE_GET_AIRLOOP_APPG.match(func_body):\n",
    "        return ComponentTypeInfo(\n",
    "            is_simple=True, simple_return=\"airLoopHVAC_->appGHeatingFuelTypes()\", func_body=func_body\n",
    "        )\n",
    "\n",
    "    if RE_GET_PLANTLOOP_APPG.match(func_body):\n",
    "        return ComponentTypeInfo(\n",
    "            is_simple=True, simple_return=\"plantLoop_->appGHeatingFuelTypes()\", func_body=func_body\n",
    "        )\n",
    "\n",
    "    s = []\n",
    "\n",
    "    if m := RE_INSERT_FUELTYPE_APPG.search(func_body):\n",
    "        s.append(m.groups()[0])\n",
    "    if RE_INSERT_CONVERTFUELTYPE_APPG.search(func_body):\n",
    "        s.append(\"fuelType()\")\n",
    "\n",
    "    if RE_INSERT_AIRLOOP_APPG.search(func_body):\n",
    "        s.append(\"airLoopHVAC_->appGHeatingFuelTypes()\")\n",
    "    if RE_INSERT_PLANTLOOP_APPG.search(func_body):\n",
    "        s.append(\"airLoopHVAC_->appGHeatingFuelTypes()\")\n",
    "    if RE_INSERT_HEAT_COIL_APPG.search(func_body):\n",
    "        s.append(\"hc.appGHeatingFuelTypes()\")\n",
    "    if RE_INSERT_OPT_HEAT_COIL_APPG.search(func_body):\n",
    "        s.append(\"hc_->appGHeatingFuelTypes()\")\n",
    "    if RE_INSERT_REHEAT_COIL_APPG.search(func_body):\n",
    "        s.append(\"reheatCoil.appGHeatingFuelTypes()\")\n",
    "    if RE_INSERT_SUPHC_COIL_APPG.search(func_body):\n",
    "        s.append(\"supHC.appGHeatingFuelTypes()\")\n",
    "    if RE_INSERT_OPT_SUPHC_COIL_APPG.search(func_body):\n",
    "        s.append(\"supHC_->appGHeatingFuelTypes()\")\n",
    "    if s:\n",
    "        # print(s)\n",
    "        return ComponentTypeInfo(is_simple=True, simple_return=\" + \".join(s), func_body=func_body)\n",
    "\n",
    "    return ComponentTypeInfo(is_simple=False, func_body=func_body)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "d5719d30",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "hc_->heatingFuelTypes() + supHC_->heatingFuelTypes()"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "func_body = \"\"\"\n",
    "{\n",
    "      std::set<FuelType> result;\n",
    "      if (auto hc_ = heatingCoil()) {\n",
    "        for (auto ft : hc_->heatingFuelTypes()) {\n",
    "          result.insert(ft);\n",
    "        }\n",
    "      }\n",
    "      // TODO: is supplemental needed?\n",
    "      if (auto supHC_ = supplementalHeatingCoil()) {\n",
    "        for (auto ft : supHC_->heatingFuelTypes()) {\n",
    "          result.insert(ft);\n",
    "        }\n",
    "      }\n",
    "\n",
    "      return {result.begin(), result.end()};\n",
    "    }\n",
    "\"\"\"\n",
    "parse_heatingFuelTypeFuncBod(func_body)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "22cdb75b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "airLoopHVAC_->appGHeatingFuelTypes() + reheatCoil.appGHeatingFuelTypes()"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "func_body = \"\"\"{\n",
    "      std::set<AppGFuelType> result;\n",
    "      if (auto hc_ = heatingCoil()) {\n",
    "        for (auto ft : hc_->appGHeatingFuelTypes()) {\n",
    "          result.insert(ft);\n",
    "        }\n",
    "      }\n",
    "      // TODO: is supplemental needed?\n",
    "      if (auto supHC_ = supplementalHeatingCoil()) {\n",
    "        for (auto ft : supHC_->appGHeatingFuelTypes()) {\n",
    "          result.insert(ft);\n",
    "        }\n",
    "      }\n",
    "      return {result.begin(), result.end()};\n",
    "    }\"\"\"\n",
    "\n",
    "func_body = \"\"\"{\n",
    "      std::set<AppGFuelType> result;\n",
    "      for (auto ft : reheatCoil().appGHeatingFuelTypes()) {\n",
    "        result.insert(ft);\n",
    "      }\n",
    "      if (auto a_ = airLoopHVAC()) {\n",
    "        for (auto ft : a_->appGHeatingFuelTypes()) {\n",
    "          result.insert(ft);\n",
    "        }\n",
    "      }\n",
    "      return {result.begin(), result.end()};\n",
    "    }\"\"\"\n",
    "parse_appGHeatingFuelTypeFuncBod(func_body)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "34dfc64b",
   "metadata": {},
   "outputs": [],
   "source": [
    "class_infos = {}\n",
    "for cpp_file in cpp_files:\n",
    "    class_name = cpp_file.name.replace(\".cpp\", \"\")\n",
    "\n",
    "    with open(cpp_file, \"r\") as f:\n",
    "        content = f.read()\n",
    "    if not \"Impl::componentType()\" in content:\n",
    "        continue\n",
    "\n",
    "    lines = content.splitlines()\n",
    "\n",
    "    class_info = ClassInfo(class_name=class_name)\n",
    "\n",
    "    i = 0\n",
    "    while i < len(lines):\n",
    "        if \"::componentType\" in lines[i]:\n",
    "            i, func_body = get_func_body(lines, i)\n",
    "            if m := RE_SIMPLE_COMPTYPE.match(func_body):\n",
    "                class_info.component_type = ComponentTypeInfo(is_simple=True, simple_return=m.groups()[0])\n",
    "            else:\n",
    "                class_info.component_type = ComponentTypeInfo(is_simple=False, func_body=func_body)\n",
    "        elif \"::coolingFuelTypes\" in lines[i]:\n",
    "            i, func_body = get_func_body(lines, i)\n",
    "            class_info.cooling_fuel_types = parse_coolingFuelTypeFuncBod(func_body=func_body)\n",
    "\n",
    "        elif \"::heatingFuelTypes\" in lines[i]:\n",
    "            i, func_body = get_func_body(lines, i)\n",
    "            class_info.heating_fuel_types = parse_heatingFuelTypeFuncBod(func_body=func_body)\n",
    "        elif \"::appGHeatingFuelTypes\" in lines[i]:\n",
    "            i, func_body = get_func_body(lines, i)\n",
    "            class_info.appg_heating_fuel_types = parse_appGHeatingFuelTypeFuncBod(func_body=func_body)\n",
    "        i += 1\n",
    "    class_infos[class_name] = class_info"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "25e2806f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ZoneHVACPackagedTerminalHeatPump,Complex,cc.coolingFuelTypes(),hc.heatingFuelTypes() + supHC.heatingFuelTypes(),hc.appGHeatingFuelTypes() + supHC.appGHeatingFuelTypes()"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "class_infos[\"ZoneHVACPackagedTerminalHeatPump\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b857ea67",
   "metadata": {},
   "source": [
    "# Print out \"complex\" types I couldn't resolve"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a6a6ce83",
   "metadata": {},
   "source": [
    "## Cooling fuel types"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "d9c6486e",
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "AirLoopHVACOutdoorAirSystem\n",
      "==============\n",
      "std::set<FuelType> result;\n",
      "      for (const auto& comp : subsetCastVector<HVACComponent>(components())) {\n",
      "        for (auto& ft : comp.coolingFuelTypes()) {\n",
      "          result.insert(ft);\n",
      "        }\n",
      "      }\n",
      "      return {result.begin(), result.end()};\n",
      "\n",
      "\n",
      "ChillerAbsorption\n",
      "==============\n",
      "if (auto generatorLoop_ = generatorLoop()) {\n",
      "        return generatorLoop_->heatingFuelTypes();  // This is done on purpose. We use heat to produce chilled water here!\n",
      "      }\n",
      "      return {};\n",
      "\n",
      "\n",
      "ChillerAbsorptionIndirect\n",
      "==============\n",
      "if (auto generatorLoop_ = generatorLoop()) {\n",
      "        return generatorLoop_->heatingFuelTypes();  // This is done on purpose. We use heat to produce chilled water here!\n",
      "      }\n",
      "      return {};\n",
      "\n",
      "\n",
      "CoilSystemIntegratedHeatPumpAirSource\n",
      "==============\n",
      "std::set<FuelType> result;\n",
      "\n",
      "      for (auto ft : spaceCoolingCoil().coolingFuelTypes()) {\n",
      "        result.insert(ft);\n",
      "      }\n",
      "\n",
      "      for (auto ft : scwhCoil().coolingFuelTypes()) {\n",
      "        result.insert(ft);\n",
      "      }\n",
      "      for (auto ft : scdwhCoolingCoil().coolingFuelTypes()) {\n",
      "        result.insert(ft);\n",
      "      }\n",
      "      for (auto ft : scdwhWaterHeatingCoil().coolingFuelTypes()) {\n",
      "        result.insert(ft);\n",
      "      }\n",
      "\n",
      "      return {result.begin(), result.end()};\n",
      "\n",
      "\n",
      "CoilWaterHeatingAirToWaterHeatPumpWrapped\n",
      "==============\n",
      "//   return {};\n",
      "    //\n",
      "\n",
      "\n",
      "HeatExchangerFluidToFluid\n",
      "==============\n",
      "const std::string controlType = this->controlType();\n",
      "      if (openstudio::istringEqual(controlType, \"HeatingSetpointModulated\") || openstudio::istringEqual(controlType, \"HeatingSetpointOnOff\")) {\n",
      "        return {};\n",
      "      }\n",
      "      if (auto p_ = secondaryPlantLoop()) {\n",
      "        return p_->coolingFuelTypes();\n",
      "      }\n",
      "\n",
      "      return {};\n",
      "\n",
      "\n",
      "ThermalStorageChilledWaterStratified\n",
      "==============\n",
      "if (auto p_ = secondaryPlantLoop()) {\n",
      "        return p_->coolingFuelTypes();\n",
      "      }\n",
      "      return {};\n",
      "\n",
      "\n",
      "ThermalZone\n",
      "==============\n",
      "std::set<FuelType> result;\n",
      "      for (const auto& comp : subsetCastVector<HVACComponent>(equipment())) {\n",
      "        for (auto& ft : comp.coolingFuelTypes()) {\n",
      "          result.insert(ft);\n",
      "        }\n",
      "      }\n",
      "      return {result.begin(), result.end()};\n",
      "\n",
      "\n",
      "WaterHeaterMixed\n",
      "==============\n",
      "std::set<FuelType> result;\n",
      "\n",
      "      if (boost::optional<PlantLoop> p_ = secondaryPlantLoop()) {\n",
      "        auto plantFuelTypes = p_->coolingFuelTypes();\n",
      "        result.insert(plantFuelTypes.begin(), plantFuelTypes.end());\n",
      "      }\n",
      "\n",
      "      return {result.begin(), result.end()};\n",
      "\n",
      "\n",
      "WaterHeaterStratified\n",
      "==============\n",
      "std::set<FuelType> result;\n",
      "\n",
      "      // TODO: only if cap == 0?\n",
      "      if (boost::optional<PlantLoop> p_ = secondaryPlantLoop()) {\n",
      "        auto plantFuelTypes = p_->coolingFuelTypes();\n",
      "        result.insert(plantFuelTypes.begin(), plantFuelTypes.end());\n",
      "      }\n",
      "\n",
      "      return {result.begin(), result.end()};\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "for k, c in class_infos.items():\n",
    "    if c.cooling_fuel_types.is_simple:\n",
    "        continue\n",
    "\n",
    "    print(f\"{c.class_name}\\n==============\\n{c.cooling_fuel_types.func_body}\\n\\n\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73a570a1",
   "metadata": {},
   "source": [
    "## Heating Fuel Types"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "dc5bcc6d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "AirLoopHVACOutdoorAirSystem\n",
      "==============\n",
      "std::set<FuelType> result;\n",
      "      for (const auto& comp : subsetCastVector<HVACComponent>(components())) {\n",
      "        for (auto& ft : comp.heatingFuelTypes()) {\n",
      "          result.insert(ft);\n",
      "        }\n",
      "      }\n",
      "      return {result.begin(), result.end()};\n",
      "\n",
      "\n",
      "CoilSystemIntegratedHeatPumpAirSource\n",
      "==============\n",
      "std::set<FuelType> result;\n",
      "\n",
      "      for (auto ft : spaceHeatingCoil().heatingFuelTypes()) {\n",
      "        result.insert(ft);\n",
      "      }\n",
      "      // TODO: include dedicatedWaterHeatingCoil? The combined space cooling + water heating ones too?\n",
      "      for (auto ft : shdwhHeatingCoil().heatingFuelTypes()) {\n",
      "        result.insert(ft);\n",
      "      }\n",
      "      for (auto ft : shdwhWaterHeatingCoil().heatingFuelTypes()) {\n",
      "        result.insert(ft);\n",
      "      }\n",
      "\n",
      "      return {result.begin(), result.end()};\n",
      "\n",
      "\n",
      "CoilWaterHeatingAirToWaterHeatPumpWrapped\n",
      "==============\n",
      "//   return {FuelType::Electricity};\n",
      "    //\n",
      "\n",
      "\n",
      "HeatExchangerFluidToFluid\n",
      "==============\n",
      "const std::string controlType = this->controlType();\n",
      "      if (openstudio::istringEqual(controlType, \"CoolingSetpointModulated\") || openstudio::istringEqual(controlType, \"CoolingSetpointOnOff\")\n",
      "          || openstudio::istringEqual(controlType, \"CoolingDifferentialOnOff\")\n",
      "          || openstudio::istringEqual(controlType, \"CoolingSetpointOnOffWithComponentOverride\")) {\n",
      "        return {};\n",
      "      }\n",
      "      if (auto p_ = secondaryPlantLoop()) {\n",
      "        return p_->heatingFuelTypes();\n",
      "      }\n",
      "\n",
      "      return {};\n",
      "\n",
      "\n",
      "ThermalZone\n",
      "==============\n",
      "std::set<FuelType> result;\n",
      "      for (const auto& comp : subsetCastVector<HVACComponent>(equipment())) {\n",
      "        for (auto& ft : comp.heatingFuelTypes()) {\n",
      "          result.insert(ft);\n",
      "        }\n",
      "      }\n",
      "      return {result.begin(), result.end()};\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "for k, c in class_infos.items():\n",
    "    if c.heating_fuel_types.is_simple:\n",
    "        continue\n",
    "\n",
    "    print(f\"{c.class_name}\\n==============\\n{c.heating_fuel_types.func_body}\\n\\n\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a56bfe86",
   "metadata": {},
   "source": [
    "## Appendix G Heating Fuel Types"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "e57e33f4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "AirLoopHVACOutdoorAirSystem\n",
      "==============\n",
      "std::set<AppGFuelType> result;\n",
      "      for (const auto& comp : subsetCastVector<HVACComponent>(components())) {\n",
      "        for (auto& ft : comp.appGHeatingFuelTypes()) {\n",
      "          result.insert(ft);\n",
      "        }\n",
      "      }\n",
      "      return {result.begin(), result.end()};\n",
      "\n",
      "\n",
      "CoilSystemIntegratedHeatPumpAirSource\n",
      "==============\n",
      "std::set<AppGFuelType> result;\n",
      "\n",
      "      for (auto ft : spaceHeatingCoil().appGHeatingFuelTypes()) {\n",
      "        result.insert(ft);\n",
      "      }\n",
      "      // TODO: include dedicatedWaterHeatingCoil? The combined space cooling + water heating ones too?\n",
      "      for (auto ft : shdwhHeatingCoil().appGHeatingFuelTypes()) {\n",
      "        result.insert(ft);\n",
      "      }\n",
      "      for (auto ft : shdwhWaterHeatingCoil().appGHeatingFuelTypes()) {\n",
      "        result.insert(ft);\n",
      "      }\n",
      "\n",
      "      return {result.begin(), result.end()};\n",
      "\n",
      "\n",
      "CoilWaterHeatingAirToWaterHeatPumpWrapped\n",
      "==============\n",
      "//   return {AppGFuelType::HeatPump};  // TODO: openstudio-standards uses Electric\n",
      "    //\n",
      "\n",
      "\n",
      "HeatExchangerFluidToFluid\n",
      "==============\n",
      "const std::string controlType = this->controlType();\n",
      "      if (openstudio::istringEqual(controlType, \"CoolingSetpointModulated\") || openstudio::istringEqual(controlType, \"CoolingSetpointOnOff\")\n",
      "          || openstudio::istringEqual(controlType, \"CoolingDifferentialOnOff\")\n",
      "          || openstudio::istringEqual(controlType, \"CoolingSetpointOnOffWithComponentOverride\")) {\n",
      "        return {};\n",
      "      }\n",
      "      if (auto p_ = secondaryPlantLoop()) {\n",
      "        return p_->appGHeatingFuelTypes();\n",
      "      }\n",
      "\n",
      "      return {};\n",
      "\n",
      "\n",
      "ThermalZone\n",
      "==============\n",
      "std::set<AppGFuelType> result;\n",
      "      for (const auto& comp : subsetCastVector<HVACComponent>(equipment())) {\n",
      "        for (auto& ft : comp.appGHeatingFuelTypes()) {\n",
      "          result.insert(ft);\n",
      "        }\n",
      "      }\n",
      "      return {result.begin(), result.end()};\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "for k, c in class_infos.items():\n",
    "    if c.appg_heating_fuel_types.is_simple:\n",
    "        continue\n",
    "\n",
    "    print(f\"{c.class_name}\\n==============\\n{c.appg_heating_fuel_types.func_body}\\n\\n\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c546ca3a",
   "metadata": {},
   "source": [
    "# Dump to CSV"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "c410f342",
   "metadata": {},
   "outputs": [],
   "source": [
    "lines = [\",\".join(ClassInfo.header())]\n",
    "for k, c in class_infos.items():\n",
    "    lines.append(c.__repr__())\n",
    "\n",
    "with open(\"FuelTypes.csv\", \"w\") as f:\n",
    "    f.write(\"\\n\".join(lines) + \"\\n\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
